<?php
/**
 * 订单号生成器
 * @author fzq
 * time 2016-08-17
 */
namespace libraries;

use enums\CachePrefixEnums;
use enums\ServiceEnums;
if( ! APP_ROOT  ) return 'Direct Access Deny!';

// $objID = new IDGenerator();
// $objID->setDI( $this->di );
// echo $objID->getID();
// echo $objID->fillIDPool( IDEnums::TYPE_PRODUCT ), '<br>';
// echo $objID->getID( IDEnums::TYPE_PRODUCT ), '<br>';

class IDGenerator implements \Phalcon\DI\InjectionAwareInterface
{
	private $_di;
	static private $_instance = null ;
	private $_redis;
	
	/**
	 * 用来生成订单ID或其它自增ID
	 * @var 
	 */
// 	static private $_prefix = CachePrefixEnums::IDG_PREFIX;

	private function __construct( $di )
	{
	    $this->setDI( $di );
	}
	
	static public function getInstance( $di )
	{
		if( is_null( self::$_instance ))
		{
			self::$_instance = new IDGenerator( $di );
		}
		return self::$_instance;
	}
	
	/* (non-PHPdoc)
	 * @see \Phalcon\Di\InjectionAwareInterface::setDI()
	*/
	public function setDI(\Phalcon\DiInterface $dependencyInjector) 
	{
		// TODO Auto-generated method stub
		$this->_di = $dependencyInjector;
		$this->_redis = $this->_di->get( ServiceEnums::SERVICE_ALI_REDIS );
	}

	/* (non-PHPdoc)
	 * @see \Phalcon\Di\InjectionAwareInterface::getDI()
	*/
	public function getDI() 
	{
		return $this->_di;
	}
	
	/**
	 * 向ID池中填充ID
	 * @param string $strType
	 * @param int $iStep
	 * @param int $iBase
	 * @param string $bGenerateCat
	 * @return -1 for error > 0 for success
	 * -1 for redis error
	 * >0 for success
	 */
// 	public function fillIDPool( $strType, $iStep = 10000, $iBase = 10000, $bGenerateCat = false )
// 	{
// 		$objRedis = $this->_di->get( 'nredis' );
// 		if( !$objRedis )
// 		{
// 			return -1;
// 		}
		
// 		$iCnt = $objRedis->lLen( self::$_prefix . $strType );
		
// 		if( $iCnt < $iStep / 2 || $iCnt < 3000 )
// 		{
// 			return $this->generateIDS( $objRedis, $strType, $iStep, $iBase, $bGenerateCat );
// 		}
		
// 		return $iCnt;
// 	}
	
	/**
	 * 真正的向ID池中填充数据
	 * @param object $objRedis
	 * @param string $strType
	 * @param int $iStep
	 * @param nuintmber $iBase
	 * @param string $bGenerateCat
	 * @return int
	 * 
	 * -1 不存在相应type的ID池
	 * -2 Base 保存失败（数据库错误）
	 * >0 成功
	 */
// 	private function generateIDS( $objRedis, $strType, $iStep = 10000, $iBase = 10000, $bGenerateCat = false )
// 	{
// 		$objBase = SystemDic::findFirst( array( "key=:name:", 'bind' => array( 'name' => $strType ) ));
		
// 		if( !$objBase && !$bGenerateCat )
// 		{
// 			return -1;
// 		}
		
// 		if( !$objBase )
// 		{
// 			$objBase = new SystemDic();
// 			$objBase->create_time = TimeUtils::getFullTime();	
// 			$objBase->update_time = TimeUtils::getFullTime();
// 			$objBase->delsign = 0;
// 			$objBase->descr = '自动生成的' . self::$_prefix . $strType;
// 			$objBase->key = self::$_prefix . $strType;
// 			$objBase->title = self::$_prefix . $strType;
// 			$objBase->valtype = 0;
// 			$objBase->value = $iBase > 0 ?: 1;//base必须大于0 
// 		}
		
// 		$iValue = $objBase->value;
		
// 		$objBase->value += $iStep;
// 		if( !$objBase->save())
// 		{
// 			return -2;
// 		}
		
// 		$strType = "'" . self::$_prefix . $strType . "'";
// 		$script = <<<EOT
// 		local iValue = $iValue;
// 		local iCnt = 0;
// 		for i=1, $iStep, 1 do
// 			iCnt = redis.call( 'lpush', $strType, i + $iValue );
// 		end
// 		return iCnt;
// EOT;
// 		return $objRedis->eval( $script );

// 	}
	
	/**
	 * 生成指定种类的order id
	 */
	public function initSequence( $strType = 'default', $iStart = 10000 )
	{
		$this->_redis->setNx( CachePrefixEnums::IDG_PREFIX . $strType, $iStart );
	}
	
	
	/**
	 * 
	 * @param string $strType
	 * @return int
	 * 
	 * -1 for redis error
	 * >0 for success
	 */
	public function getID( $strType = 'default' )
	{
// 		$objRedis = $this->_di->get( 'nredis' );
// 		if( !$objRedis )
// 		{
// 			return -1;
// 		}
		
		return $this->_redis->incr( CachePrefixEnums::IDG_PREFIX . $strType );
		
// 		$iID = $objRedis->rpop( self::$_prefix . $strType );
	
// 		if( $iID )
// 		{
// 			return $iID;
// 		}
		
// 		if( $this->generateIDS($objRedis, $strType) < 0 )
// 			return -1;
		
// 		$iID = $objRedis->rpop( self::$_prefix . $strType );
// 		if( $iID )
// 		{
// 			return $iID;
// 		}
// 		return -1;
	}
}